﻿using Microsoft.Xna.Framework;
using ShevaEngine.Core.Interfaces;
using System.Collections.Generic;
using System;
using ShevaEngine.Core.GameLogic.Triggers.Collision_Triggers;

namespace ShevaEngine.Core.GameLogic.Triggers
{
    /// <summary>
    /// Triggers manager.
    /// </summary>
    public class TriggersManager :IUpdateAble
    {
        /// <summary>Collision triggers.</summary>
        private List<CollisionTrigger> CollisionTriggers;
        /// <summary>Collisions.</summary>
        private TriggerState[][] CollisionTriggersRelations;

        /// <summary>
        /// Constructor.
        /// </summary>
        public TriggersManager()
        {
            this.CollisionTriggers = new List<CollisionTrigger>();
            this.CollisionTriggersRelations = new TriggerState[0][];
        }

        /// <summary>
        /// Method adds trigger.
        /// </summary>
        public void AddTrigger(Trigger trigger)
        {
            if (trigger is CollisionTrigger)
            {
                this.CollisionTriggers.Add(trigger as CollisionTrigger);

                Array.Resize<TriggerState[]>(ref this.CollisionTriggersRelations, this.CollisionTriggers.Count);

                TriggerState[] temp = new TriggerState[this.CollisionTriggers.Count - 1];

                for (int i = 0; i < temp.Length; i++)
                    temp[i] = TriggerState.None;

                this.CollisionTriggersRelations[this.CollisionTriggers.Count - 1] = temp;
            }
        }

        /// <summary>
        /// Method Update.
        /// </summary>
        /// <param name="time"></param>
        public void Update(GameTime time)
        {
            this.UpdateCollisionTriggers(time);
        }

        /// <summary>
        /// Update collision triggers.
        /// </summary>
        /// <param name="time"></param>
        private void UpdateCollisionTriggers(GameTime time)
        {
            for (int i = this.CollisionTriggers.Count - 1; i >= 0; i--)
                for (int j = (i - 1); j >= 0; j--)
                {
                    if (this.CollisionTriggers[i] is CircleCollisionTrigger)
                        if (this.CollisionTriggers[j] is CircleCollisionTrigger)
                        {
                            bool collide =
                                CircleCollisionTrigger.Collide(
                                    this.CollisionTriggers[i] as CircleCollisionTrigger,
                                    this.CollisionTriggers[j] as CircleCollisionTrigger);

                            if (collide != ((this.CollisionTriggersRelations[i][j] & TriggerState.Collision) == TriggerState.Collision))
                            {
                                TriggerEventArgs e;

                                if (collide)
                                {
                                    e = new TriggerEventArgs(TriggerEventType.Collision,
                                        this.CollisionTriggers[i] as CircleCollisionTrigger,
                                        this.CollisionTriggers[j] as CircleCollisionTrigger);

                                    this.CollisionTriggers[i].TriggerEntered(this, e);
                                    this.CollisionTriggers[j].TriggerEntered(this, e);

                                    this.CollisionTriggersRelations[i][j] = this.CollisionTriggersRelations[i][j] | TriggerState.Collision;
                                }
                                else
                                {
                                    e = new TriggerEventArgs(TriggerEventType.EndCollision,
                                            this.CollisionTriggers[i] as CircleCollisionTrigger,
                                            this.CollisionTriggers[j] as CircleCollisionTrigger);

                                    this.CollisionTriggers[i].TriggerLeaved(this, e);
                                    this.CollisionTriggers[j].TriggerLeaved(this, e);

                                    this.CollisionTriggersRelations[i][j] = this.CollisionTriggersRelations[i][j] & ~TriggerState.Collision;
                                }

                                
                            }
                        }
                }
        }
    }

    /// <summary>
    /// Trigger state.
    /// </summary>
    public enum TriggerState : int
    {
        None = 0x0,
        Collision = 0x1,
    }
}
